#include "CapitalMarketSettings.h"
#include <array>
#include <core/FileSys.h>
#include <core/Utility.h>
#include <QFile>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonValue>


const std::vector<QString> groupName = { "DR", "GC", "IRS", "Shibor", "FR", "FDR" };
//const std::vector<int> groupVersion = { 20210507, 20210507, 20210507, 20210507, 20210507, 20210507 };
const int kGroupVersion = 20210507;
const std::vector<QString> groupDR = { "DR001", "DR007", "DR014", "DR021", "DR1M", "DR2M" };
const std::vector<QString> groupGC = { "GC001", "GC007", "GC014", "GC002", "GC003", "GC004", "GC028", "GC091", "GC182" };
const std::vector<QString> groupShibor = { "Shi O/N", "Shi 1W", "Shi 3M", "Shi 2W", "Shi 1M", "Shi 6M", "Shi 9M","Shi 1Y" };
const std::vector<QString> groupFR = { "FR001", "FR007", "FR014" };
const std::vector<QString> groupFDR = { "FDR001", "FDR007",	"FDR014" };

const std::vector<QString> groupIRS = { "IRS FR1Y", "IRS FR5Y", "IRS Shi1Y", "IRS Shi5Y" };
const std::vector<QString> groupIndex = {
    "上证指数",
    "沪深300",
    "深证成指",
    "美元指数",
    "创业板指",
    "10Y美债",
    "WTI原油",
    "布伦特原油",
    "富时A50",
    "恒生指数",
    "VIX指数"
};

const int MaxCountPerGroup=100;// 注意：每种预留100个
enum CapitalMarketItemID {
    DR001 = CapitalMarketSettings::DR * MaxCountPerGroup,
    DR007,
    DR014,
    DR021,
    DR1M,
    DR2M,

    GC001 = CapitalMarketSettings::GC * MaxCountPerGroup,
    GC007,
    GC014,
    GC002,
    GC003,
    GC004,
    GC028,
    GC091,
    GC182,

    Shibor_ON = CapitalMarketSettings::Shibor * MaxCountPerGroup,
    Shibor_1W,
    Shibor_3M,
    Shibor_2W,
    Shibor_1M,
    Shibor_6M,
    Shibor_9M,
    Shibor_1Y,

    FR001 = CapitalMarketSettings::FR * MaxCountPerGroup,
    FR007,
    FR014,

    FDR001 = CapitalMarketSettings::FDR * MaxCountPerGroup,
    FDR007,
    FDR014,

    IRS_FR1Y = CapitalMarketSettings::IRS * MaxCountPerGroup,
    IRS_FR5Y,
    IRS_SHIBOR1Y,
    IRS_SHIBOR5Y,

    SSEC = CapitalMarketSettings::Index * MaxCountPerGroup,		//上证指数
    CSI300,		//沪深300
    SZI,		//深证成指
    USDX,		//美元指数
    GEM,		//创业板指
    US10YR,		//10Y美债
    WTICRUDE,	//WTI原油
    BRENTCRUDE,  //布伦特原油
    XIN9,	    //富时A50
    HSI,		//恒生指数
    VIX,		//VIX指数
};

const char kFundsCfgFileName[] = "/CapitalMarketFunds.json";
const char kAssetsCfgFileName[] = "/CapitalMarketAssets.json";
const char* kCfgFileNames[CapitalMarketSettings::MaxCount] = {kFundsCfgFileName, kAssetsCfgFileName};

CapitalMarketSettings::CapitalMarketSettings(const CapitalMarketType& type):QObject(), m_type(type)
{

}

CapitalMarketSettings& CapitalMarketSettings::instance(const CapitalMarketType& type)
{
    static CapitalMarketSettings FundsOrderData(Funds);
    static CapitalMarketSettings AssetsOrderData(Assets);

    return (type == Funds) ? FundsOrderData : AssetsOrderData;
}

void CapitalMarketSettings::loadRecord()
{
    m_record.clear();

    QString recordPath = FileSys::instance()->userCfgDir() + kCfgFileNames[m_type];

	QJsonDocument doc = CoreUtility::openJsonDoc(recordPath);
	if (!doc.isNull())
	{
		QJsonObject mmObj = doc.object();
        const QJsonArray& order = mmObj["order"].toArray();
        for(const auto& i : order) {
            m_record.push_back(i.toInt());
        }
	}
	else
	{
        m_record = getDefaultOrder();
        saveRecord();
	}

}

void CapitalMarketSettings::saveRecord()
{
	QJsonObject recordObj;
	{
		QJsonArray orderAry;
        for (const auto& item : m_record)
		{
            orderAry.append(item);
		}

        recordObj.insert("order", orderAry);
        recordObj.insert("version", kGroupVersion);
	}
	QJsonDocument jdoc;
	jdoc.setObject(recordObj);
    QFile mmFile(FileSys::instance()->userCfgDir() + kCfgFileNames[m_type]);
	if (mmFile.open(QIODevice::WriteOnly))
	{
		mmFile.write(jdoc.toJson(QJsonDocument::Indented));
	}
	mmFile.close();
}

const int getSubIndex(const int &id) {
    return (id % MaxCountPerGroup);
}

const QString CapitalMarketSettings::getName(const int &id)
{
    const std::array<const std::vector<QString>*, 7> kId2Names= {
        &groupDR,
        &groupGC,
        &groupShibor,
        &groupFR,
        &groupFDR,
        &groupIRS,
        &groupIndex
    };
    const int index = (id / MaxCountPerGroup);
    const int sub_index = getSubIndex(id);

    if ((index >= 0) && (index < (int)kId2Names.size())) {
        const std::vector<QString>* group = kId2Names[index];
        if ((sub_index >= 0) && (sub_index < (int)group->size())) {
            return (*group)[sub_index];
        }
    }

    return QString("Invalid Id %1").arg(id);
}

const int CapitalMarketSettings::getBaseId(const CapitalMarketGroupID &group_id)
{
    return group_id * MaxCountPerGroup;
}

const int kFundsTakeCount = 3;
std::vector<int> CapitalMarketSettings::getDefaultOrder() const
{
    std::vector<int> all = getAllOrder();
    if (m_type == Funds) {
        std::vector<int> funds;
        std::copy_if(all.begin(), all.end(), std::back_inserter(funds), [](const int& id) {
            const int sub_index = getSubIndex(id);
            return (sub_index < kFundsTakeCount) && (sub_index >= 0);
        });

        return funds;
    }

    return all;
}

std::vector<int> CapitalMarketSettings::getAllOrder() const
{
    if (m_type == Funds) {
        std::vector<int> ret = {
            DR001,
            DR007,
            DR014,
            DR021,
            DR1M,
            DR2M,

            GC001,
            GC007,
            GC014,
            GC002,
            GC003,
            GC004,
            GC028,
            GC091,
            GC182,

            Shibor_ON,
            Shibor_1W,
            Shibor_3M,
            Shibor_2W,
            Shibor_1M,
            Shibor_6M,
            Shibor_9M,
            Shibor_1Y,

            FR001,
            FR007,
            FR014,

            FDR001,
            FDR007,
            FDR014,
        };

        return ret;
    } else if (m_type == Assets) {
        std::vector<int> ret =  {
            SSEC,
            CSI300,
            SZI,
            GEM,
            USDX,
            US10YR,
            WTICRUDE,
            BRENTCRUDE,
            XIN9,
            HSI,
            VIX,
            IRS_FR1Y,
            IRS_FR5Y,
            IRS_SHIBOR1Y,
            IRS_SHIBOR5Y,
        };

        return ret;
    }

    return {};
}

void CapitalMarketSettings::setOrder(const std::vector<int> &order)
{
    m_record = order;
    emit orderChanged();
}

void CapitalMarketSettings::setOrder(std::vector<int> &&order)
{
    m_record = std::move(order);
    emit orderChanged();
}
